package com.gitee.zhuhjay.xunfei.sdk.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.gitee.zhuhjay.xunfei.sdk.consts.ApiVersion;
import com.gitee.zhuhjay.xunfei.sdk.consts.ConfigConst;
import com.gitee.zhuhjay.xunfei.sdk.model.ApiAuth;
import com.gitee.zhuhjay.xunfei.sdk.model.Function;
import com.gitee.zhuhjay.xunfei.sdk.model.ModelParams;
import com.gitee.zhuhjay.xunfei.sdk.model.Text;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

import static cn.hutool.core.date.DatePattern.HTTP_DATETIME_FORMAT;

/**
 * @author ZhuHJay
 * @since 2023/11/2 9:24
 */
public class XfUtil {

    /**
     * 生成授权url
     *
     * @param apiAuth api授权信息
     * @param version api版本
     * @param isWss   是否使用wss协议
     * @return url
     */
    public static String genAuthUrl(ApiAuth apiAuth, ApiVersion version, boolean isWss) {
        // date
        String date = DateUtil.format(DateUtil.date(), HTTP_DATETIME_FORMAT);
        String host = ConfigConst.HOST;
        String path = version.getPath();

        // authorization
        String tmp = StrBuilder.create()
                .append("host: ").append(host).append("\n")
                .append("date: ").append(date).append("\n")
                .append("GET ").append(path).append(" HTTP/1.1").toString();
        // 加密摘要
        byte[] tmpSha = new HMac(
                HmacAlgorithm.HmacSHA256,
                apiAuth.getApiSecret().getBytes(StandardCharsets.UTF_8)
        ).digest(tmp.getBytes(StandardCharsets.UTF_8));
        String signature = Base64.encode(tmpSha);
        // 数据拼接
        String authorizationOrigin = StrBuilder.create()
                .append("api_key=\"").append(apiAuth.getApiKey()).append("\", ")
                .append("algorithm=\"").append("hmac-sha256").append("\", ")
                .append("headers=\"").append("host date request-line").append("\", ")
                .append("signature=\"").append(signature).append("\"").toString();
        String authorization = Base64.encode(authorizationOrigin);
        // url
        String url = StrUtil.format("{}://{}{}", isWss ? "wss" : "ws", host, path);
        return HttpUtil.encodeParams(StrUtil.format("{}?authorization={}&date={}&host={}",
                url, authorization, date, host), StandardCharsets.UTF_8);
    }

    /**
     * 生成授权url(使用ws协议)
     *
     * @param apiAuth api授权信息
     * @param version api版本
     * @return url
     */
    public static String genAuthUrl(ApiAuth apiAuth, ApiVersion version) {
        return genAuthUrl(apiAuth, version, false);
    }

    /**
     * 生成请求消息
     *
     * @param apiAuth   api授权信息
     * @param version   api版本
     * @param params    模型参数
     * @param text      文本，可以包括历史信息
     * @param functions function方法注册信息(只有v3.0版本及其以上版本才会生效)
     * @return 请求消息
     */
    public static String genReqMessage(
            ApiAuth apiAuth, ApiVersion version, ModelParams params, List<Text> text, List<Function> functions) {
        Dict header = Dict.create()
                .set("app_id", apiAuth.getAppId());
        Dict parameter = Dict.create()
                .set("chat", Dict.create()
                        .set("domain", version.getDomain())
                        .set("temperature", params.getTemperature())
                        .set("max_tokens", params.getMaxTokens())
                        .set("top_k", params.getTopP()));
        Dict payload = Dict.create()
                .set("message", Dict.create()
                        .set("text", text));
        // v3.0版本及其以上版本才支持 function
        if ((ApiVersion.V3_0 == version || ApiVersion.V3_5 == version) && functions != null) {
            payload.set("functions", Dict.create()
                    .set("text", functions));
        }
        return JSONUtil.toJsonStr(Dict.create()
                .set("header", header)
                .set("parameter", parameter)
                .set("payload", payload));
    }

    /**
     * 检查qps是否合法
     *
     * @param qps qps
     */
    public static void checkQps(int qps) {
        if (qps <= 0 || qps > ConfigConst.API_MAX_QPS) {
            throw new IllegalArgumentException("qps must be in (0, 50]");
        }
    }

    /**
     * 批量检查qps是否合法
     *
     * @param qps qps
     */
    public static void checkBatchQps(int... qps) {
        Arrays.stream(qps).forEach(XfUtil::checkQps);
    }

}
